<?php
/**
 * User: 269995848@qq.com
 * Date: 2019/3/4 11:18
 */

namespace app\qqbot\service\event;


use app\lib\enum\QqBot;
use app\qqbot\service\src\Config;
use app\qqbot\service\src\CQCode;

class SendMessageEvent{

    /**
     * 给事件产生者发送私聊
     * @param string $msg 消息内容
     * @param bool $auto_escape 是否发送纯文本
     * @param bool $async 是否异步
     * @return Message
     */
    public function sendPM(string $msg,$event ,bool $auto_escape = false, bool $async = false):Message{
        

        return new Message($msg, $event['user_id'], false, $auto_escape, $async);
    }

    /**
     * 消息从哪来发到哪
     * @param string $msg 消息内容
     * @param bool $auto_escape 是否发送纯文本
     * @param bool $async 是否异步
     * @return Message
     */
    public static function sendBack(string $msg,array $event,bool $auto_escape = false, bool $async = true):Message{

        return new Message($msg, isset($event['group_id'])?$event['group_id']:$event['user_id'], isset($event['group_id']), $auto_escape, $async);
    }

    /**
     * 发送给 Master
     * @param string $msg 消息内容
     * @param bool $auto_escape 是否发送纯文本
     * @param bool $async 是否异步
     * @return Message
     */
    public static function sendMaster(string $msg,$master, bool $auto_escape = false, bool $async = true):Message{
        return new Message($msg, $master, false, $auto_escape, $async);
    }

    /**
     * 记录数据
     * @param string $filePath 相对于 storage/data/ 的路径
     * @param $data 要存储的数据内容
     * @param bool $pending 是否追加写入（默认不追加）
     * @return mixed string|false
     */
    public function setData(string $filePath, $data, bool $pending = false){
        if(!file_exists(dirname('../storage/data/'.$filePath))) if(!mkdir(dirname('../storage/data/'.$filePath), 0777, true))throw new \Exception('Failed to create data dir');
        return file_put_contents('../storage/data/'.$filePath, $data, $pending?(FILE_APPEND | LOCK_EX):LOCK_EX);
    }

    /**
     * 读取数据
     * @param $filePath 相对于 storage/data/ 的路径
     * @return mixed string|false
     */
    public function getData(string $filePath){
        return file_get_contents('../storage/data/'.$filePath);
    }

    /**
     * 缓存
     * @param string $cacheFileName 缓存文件名
     * @param $cache 要缓存的数据内容
     * @return mixed string|false
     */
    public function setCache(string $cacheFileName, $cache){
        return file_put_contents('../storage/cache/'.$cacheFileName, $cache, LOCK_EX);
    }


    /**
     * 发送图片
     * @param string $str 图片（字符串形式）
     * @return string 图片对应的 base64 格式 CQ码
     */
    public function sendImg($str):string{
        return CQCode::Image('base64://'.base64_encode($str));
    }

    /**
     * 发送录音
     * @param string $str 录音（字符串形式）
     * @return string 录音对应的 base64 格式 CQ码
     */
    public function sendRec($str):string{
        return CQCode::Record('base64://'.base64_encode($str));
    }



    /**
     * 解析命令
     * @param string $str 命令字符串
     * @return mixed array|bool 解析结果数组 失败返回false
     */
    public function parseCommand(string $str){
        // 正则表达式
        $regEx = '#(?:(?<s>[\'"])?(?<v>.+?)?(?:(?<!\\\\)\k<s>)|(?<u>[^\'"\s]+))#';
        // 匹配所有
        if(!preg_match_all($regEx, $str, $exp_list)) return false;
        // 遍历所有结果
        $cmd = array();

        foreach ($exp_list['s'] as $id => $s) {
            // 判断匹配到的值
            $cmd[] = empty($s) ? $exp_list['u'][$id] : $exp_list['v'][$id];
        }
        return $cmd;
    }

    public function isMaster($event){
        

        return $event['user_id']==config('master');
    }

    public function requireMaster(){
        if(!isMaster()){
            throw new UnauthorizedException();
        }
    }

    public function nextArg(){
        global $Command;
        static $index=0;

        return $Command[$index++];
    }

    /**
     * 冷却
     * 不指定冷却时间时将返回与冷却完成时间的距离，大于0表示已经冷却完成
     * @param string $name 冷却文件名称，对指定用户冷却需带上Q号
     * @param int $time 冷却时间
     */
    public function coolDown(string $name, $time = NULL):int{
        
        if(NULL === $time){
            clearstatcache();
            return time() - filemtime("../storage/data/coolDown/{$name}")-(int)getData("coolDown/{$name}");
        }else{
            setData("coolDown/{$name}", $time);
            return -$time;
        }
    }

    /**
     * 消息是否来自(指定)群
     * 指定参数时将判定是否来自该群
     * 不指定时将判定是否来自群聊
     * @param mixed $group=NULL 群号
     * @return bool
     */
    public function fromGroup($group = NULL):bool{
        
        if($group == NULL){
            return isset($Event['group_id']);
        }else{
            return ($Event['group_id'] == $group);
        }
    }

    /**
     * 退出模块
     * @param string $msg 返回信息
     * @param int $code 指定返回码
     * @throws Exception 用于退出模块
     */
    public function leave($msg = '', $code = 0){
        throw new \Exception($msg, $code);
    }

    /**
     * 检查是否在黑名单中
     * @return bool
     */
    public function inBlackList($qq):bool{
        $blackList = getData('blacklist.json');
        if($blackList === false)return false; //无法打开黑名单时不再抛异常
        $blackList = json_decode($blackList)->list;
        foreach($blackList as $person){
            if($qq == $person->id){
                return true;
            }
        }
        return false;
    }

    public function block($qq){
        if(inBlackList($qq))throw new UnauthorizedException();
    }


}